package tfd.scala.squib.demo.scenario;

import java.awt.{BasicStroke, Color, Dimension, Graphics2D, Image, Paint, Point, RenderingHints, Stroke}
import java.awt.event.{MouseWheelEvent}
import java.awt.image.{BufferedImage}
import java.io.{FileInputStream}
import javax.imageio.{ImageIO}
import javax.swing.{JFileChooser, JFrame}
import javax.swing.filechooser.{FileNameExtensionFilter}

import com.sun.scenario.scenegraph.{SGNode}
import com.sun.scenario.animation._

import tfd.scala.squib._
import tfd.scala.squib.event.{actionPerformed, componentResized, mouseWheelMoved }
import tfd.scala.squib.scenario.scenegraph._
import tfd.scala.squib.scenario.scenegraph.event.{mousePressed, mouseEntered, mouseExited}
import tfd.scala.squib.scenario.scenegraph.Implicits._

object PictureViewer extends Application {
    var rotateClip:Clip = null
    var imageLoaded = false;
    var picture:BufferedImage =  new BufferedImage(320, 200, BufferedImage.TYPE_4BYTE_ABGR);
    
    def scalePictureToSize() = {
        val pictureWidth = picture.getWidth()
        val pictureHeight = picture.getHeight()
        val contentSize = contentPane.getSize()
        val scalex = contentSize.getWidth() / pictureWidth
        val scaley = contentSize.getHeight() / pictureHeight
        val scalefactor = Math.min(scalex, scaley)
        scaleImage.setScaleX(scalefactor)
        scaleImage.setScaleY(scalefactor) 
        centerImage.setTranslateX(contentSize.getWidth() / 2)
        centerImage.setTranslateY(contentSize.getHeight() / 2)
        unCenterImage.setTranslateX((-pictureWidth /2) * scalefactor)
        unCenterImage.setTranslateY((-pictureHeight /2) * scalefactor)
    }
    
    def createCommonButtonImage() = {
    	val image = new BufferedImage(32, 32, BufferedImage.TYPE_4BYTE_ABGR)
        val graphics = image.getGraphics.asInstanceOf[Graphics2D]
        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON)
        graphics.setPaint(Color.BLACK)
        graphics.fillRect(0, 0, 32, 32)
        graphics.setPaint(Color.YELLOW)
        graphics.setStroke(new BasicStroke(5.0f));
    	graphics.drawRect(0, 0, 32, 32);
        image
    }
    
    // Draw "filler" image
    var graphics = picture.getGraphics.asInstanceOf[Graphics2D]
    graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                              RenderingHints.VALUE_TEXT_ANTIALIAS_ON)
    graphics.setPaint(Color.BLACK)
    graphics.fillRect(0,0,320,200)
    graphics.setPaint(Color.WHITE)
    graphics.drawString("Image Not Loaded", 100 ,100)

    val counterClockWiseImage = createCommonButtonImage() 
    graphics = counterClockWiseImage.getGraphics.asInstanceOf[Graphics2D]
    graphics.setPaint(Color.WHITE)
    graphics.setStroke(new BasicStroke(2.5f))
    graphics.drawArc(6,6,20,20,0,270)
    graphics.drawLine(16,26,20,26)
    graphics.drawLine(20,26,16,22)
    graphics.drawLine(20,26,16,28)
    graphics.drawLine(16,22,16,28)
              
    val clockWiseImage = createCommonButtonImage()
    graphics = clockWiseImage.getGraphics.asInstanceOf[Graphics2D]
    graphics.setPaint(Color.WHITE)
    graphics.setStroke(new BasicStroke(2.5f))
    graphics.drawArc(6,6,20,20,180,-270)
    graphics.drawLine(16,26,12,26)
    graphics.drawLine(12,26,16,22)
    graphics.drawLine(12,26,16,28)
    graphics.drawLine(16,22,16,28)
    
    lazy val centerImage = translate.id("center")
    lazy val unCenterImage = translate.id("uncenter")
    lazy val scaleImage = scale.id("image")
    lazy val scaleZoom = scale.id("zoom")
    lazy val contentPane = frame.id("main").getContentPane()
    lazy val rotateImage = rotate.id("image")
    lazy val compositeCounterClockWise = composite.id("counterclockwise")
    lazy val compositeClockWise = composite.id("clockwise")
       
    lazy val fileChooser = {
        val chooser = new JFileChooser()
        val filter = new FileNameExtensionFilter("JPG, GIF, or PNG Images", "jpg", "gif", "png")
        chooser.setFileFilter(filter)
        chooser
    }
    
    lazy val frm:JFrame = frame("main",
            'title->"SQUIB Picture Viewer",
            'visible -> true,
            'defaultCloseOperation -> JFrame.EXIT_ON_CLOSE,
            'size -> dimension(800,600),
            'layout -> borderlayout(),
            'jmenubar -> menubar(
                    contents(
                        menu(
                            'text-> "File",
                            'mnemonic->'F',
                            contents(
                                menuitem('text->"Open",
                                            'mnemonic -> 'O',
                                       actionPerformed {
                                           if (fileChooser.showOpenDialog(frm) == JFileChooser.APPROVE_OPTION) {
                                               try {
                                                   picture = ImageIO.read(new FileInputStream(fileChooser.getSelectedFile()))
                                                   imageLoaded = true
                                                   image.id("picture").setImage(picture)
                                                   scalePictureToSize()
                                                   scaleZoom.setScaleX(1.0)
                                                   scaleZoom.setScaleY(1.0)
                                                   rotateImage.setRotation(0)
                                               } catch  {
                                                   case ex:Exception => System.err.println(ex.toString)
                                                                        System.exit(1)
                                               }     
                                           }
                                       }
                                ),
                                menuitem('text->"Close",
                                         'mnemonic -> 'C',
                                    actionPerformed {
                                        System.exit(0);
                                    }
                                )
                            )
                        )
                    )
            ),
            contents (
             	scenepanel("scenepanel",
                        'background -> Color.BLACK,
             	        'scene -> group(
                                     translate("center", 0, 0, 
                                       rotate("image", 0.0 ,
                                         scale("zoom", 1.0, 1.0,
                                    	 translate("uncenter", 0, 0,  
                                           scale("image", 1.0, 1.0,
                                    	    image("picture", 'image->picture)
                                  ))))),
                                  group(
                                      composite("counterclockwise", 0.25,
                                           image('image-> counterClockWiseImage,
                                                 'location -> new Point(2,2),
                                                    mousePressed {
                                                          if (imageLoaded &&  (rotateClip == null || !rotateClip.isRunning)) {
                                                               val rotation = rotateImage.getRotation 
                                                            rotateClip = Clip.create(
                                                                                  300,
                                                                                   1,
                                                                                   rotateImage, 
                                                                                   "rotation", 
                                                                                   Array(rotation, rotation - java.lang.Math.PI/2).map(_.asInstanceOf[Object]):_*)
                                                                           rotateClip.start()
                                                        }
                                                    },                                                                           
                                                    mouseEntered { compositeCounterClockWise.setOpacity(0.85f) },
                                                    mouseExited { compositeCounterClockWise.setOpacity(0.25f) }
                                      		)
                                       ),
                                      composite("clockwise", 0.25,
                                           image('image-> clockWiseImage,
                                                     'location -> new Point(36,2),
                                                     mousePressed {
                                                 	       if (imageLoaded &&  (rotateClip == null || !rotateClip.isRunning)) {
                                                  	           val rotation = rotateImage.getRotation 
                                                               rotateClip = Clip.create(
                                                                                   300,
                                                                                    1,
                                                                                    rotateImage, 
                                                                                    "rotation", 
                                                                                     Array(rotation, rotation + java.lang.Math.PI/2).map(_.asInstanceOf[Object]):_*)
                                                                             rotateClip.start()
                                                          }
                                                     },                                                                                          
                                                     mouseEntered { compositeClockWise.setOpacity(0.85f) },
                                                     mouseExited { compositeClockWise.setOpacity(0.25f) }
                                          )
                                       )
                               )
                         ),
                         mouseWheelMoved { mwe:MouseWheelEvent => 
                             if (imageLoaded) { 
                                  val wheelRotation = mwe.getWheelRotation()
                                  val zoomScale = scaleZoom.getScaleX() * (1 - (wheelRotation/20.0))
                                  scaleZoom.setScaleX(zoomScale)
                                  scaleZoom.setScaleY(zoomScale)
                             }
                         }         
                	)
                
             ),
             componentResized {
                scalePictureToSize()
             } 
    )
    frm
}
